package org.seratic.enterprise.movil.chatsocket.manager;

/**
 *
 * @author david.fernandez
 */

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;

import org.seratic.enterprise.movil.chatconexion.ConexionChat;

import org.seratic.enterprise.movil.chatsocket.com.Sender;
import org.seratic.enterprise.movil.chatsocket.vo.ClienteInfo;

public class ClienteManager implements Runnable{
    
	public static final String CONEXION_EXITOSA = "Conexion exitosa";
	public static final String ERROR_CONEXION = "Error al conectar";
    private DataInputStream is;
    private DataOutputStream os;
    private ConexionChat conexionChat;
    

	private Sender sender;

    private String opciones[];
    private ClienteInfo clienteInfo=null;
    
    private ClienteListener clienteListener;
    Vector listaUsuariosCercanos;
    
    private static ClienteManager instance;

    public static ClienteManager getInstance(){
		 if(instance==null)
		 {
		  instance = new ClienteManager();
		 } 
		 
		 return instance;
    }

    
    public void setClienteListener(ClienteListener clienteListener) {
    	this.clienteListener = clienteListener;
    }

    public ClienteManager(ClienteListener cl,ConexionChat cxChat) {
        clienteListener=cl;
        this.conexionChat = cxChat;
        listaUsuariosCercanos=new Vector();
        initCliente();
    }


    public ClienteManager() {
		super();
	}

	public void start() {
		Thread t = new Thread(this);
		t.start();
    }

    public void run() {
		try {
		    conectar();
		    is = conexionChat.getDataInputStream();
		    os = conexionChat.getDataOutputStream();
	
		    sender = new Sender(os);
	        sendInit();
	        recibirUsuariosCercanos();
		    // Loop forever, receiving data
	        String msj="";
	        clienteListener.showConsola(CONEXION_EXITOSA);
		    while (true) {
			     procesarComando();
	             if (msj==null)
	                break;
		    }
		    stop();
	        clienteListener.showConsola("Conexion cerrada");
		} catch (IOException ioe) {
		    System.out.println(System.currentTimeMillis()+": Error de conexion IO");
	        clienteListener.showConsola(ERROR_CONEXION);
		} catch (Exception e) {
		    e.printStackTrace();
		}
    }

    public void stop() {
        
    }

    private void sendInit() {
        sender.sendCommand(Constantes.COMMAND_WELCOME);
        sender.send(Constantes.MSJ_BIENVENIDA);
        sender.send(clienteInfo.getId());
        sender.send(clienteInfo.getAlias());
        sender.send(clienteInfo.getBssId()!=null?clienteInfo.getBssId():"");
        sender.send(clienteInfo.getUbicacion()!=null?clienteInfo.getUbicacion().toString():"");
        sender.sendInt(clienteInfo.getFoto()!=null?clienteInfo.getFoto().length:1);
        sender.sendBytes(clienteInfo.getFoto()!=null?clienteInfo.getFoto():new byte[]{0});
        sender.sendByte(clienteInfo.getSemaforo());
        sender.sendByte(clienteInfo.getSexo());
        sender.send(clienteInfo.getDescripcion());
    }

    public void initCliente() {
        clienteInfo= new ClienteInfo();
        clienteInfo.setId(""+System.currentTimeMillis());
        clienteInfo.setAlias("UsuarioSeratic");
    }

     private void procesarComando() throws IOException {
        byte comando=is.readByte();
        switch (comando)
        {
            case Constantes.COMMAND_SEND:
                recibirMensaje();
                break;
            case Constantes.COMMAND_ADD_CLIENTE:
                agregarCliente();
                break;
            case Constantes.COMMAND_REMOVE_CLIENTE:
                removerCliente();
                break;
        }
    }

    private void recibirUsuariosCercanos() {
        try {
        	if (listaUsuariosCercanos!=null)
        	{
        		listaUsuariosCercanos.removeAllElements();
        		//listaUsuariosCercanos=null;
        		System.gc();
        	}
            short numUsuarios=is.readShort();

            if (numUsuarios<=0)
            	return;

            
            System.out.println("------------------------------");

            System.out.println("Numero de usuarios cercanos: " + numUsuarios);
            for (int i = 0; i < numUsuarios; i++) {

                 ClienteInfo ci= new ClienteInfo(is.readUTF());
                 byte[] foto= new byte[is.readInt()];
                 is.read(foto);
                 ci.setFoto(foto);
                 ci.setSemaforo((byte) is.read());
                 ci.setSexo((byte) is.read());
                 listaUsuariosCercanos.addElement(ci);
                 System.out.println("Usuario Alias: " + ci.getAlias());
                 System.out.println("Usuario ID: " + ci.getId());
                 System.out.println("------------------------------");
            }
            clienteListener.recibirClientesCercanos();

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void recibirMensaje() {
        try {
        	String valor = is.readUTF();
            int idx=valor.indexOf("|");
            String idCliente=valor.substring(0,idx);
            String msj=valor.substring(idx+1);
            
            System.out.println("Mensaje recibido:["+idCliente + msj);
            clienteListener.recibirMensaje(msj,idCliente);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public void enviar(String string) {
        System.out.println("Enviando: "+string );
        sender.sendCommand(Constantes.COMMAND_SEND);
        sender.send(string);
    }

    public void enviarTo(String msj, String idUsuario) {
        System.out.println("Enviando TO: "+msj+", al id: "+idUsuario );
        sender.sendCommand(Constantes.COMMAND_SEND_TO);
        sender.send(msj);
        sender.send(idUsuario);
    }

    private void conectar() throws Exception {
        conexionChat.conectar();
    }

    public Vector getListaUsuariosCercanos() {
        return listaUsuariosCercanos;
    }

    public ClienteInfo getClienteInfo() {
        return clienteInfo;
    }

    public void setClienteInfo(ClienteInfo clienteInfo) {
        this.clienteInfo = clienteInfo;
    }

    private void agregarCliente() {
        //Leer el cliente enviado:
        ClienteInfo ciNuevo;
        try {
            ciNuevo = new ClienteInfo(is.readUTF());
        } catch (IOException ex) {
            ex.printStackTrace();
            return;
        }
        //Verificar que el cliente ya este:
        ClienteInfo ci=null;
        boolean repetido=false;
        for (int i = 0; i < listaUsuariosCercanos.size(); i++)
        {
            ci=(ClienteInfo) listaUsuariosCercanos.elementAt(i);
            if (ci.getId().equals(ciNuevo.getId()))
            {
                repetido=true;
                break;
            }
        }
        if (!repetido)
        {
            listaUsuariosCercanos.addElement(ciNuevo);
            clienteListener.recibirClientesCercanos();
        }
    }

    private void removerCliente() {
        //Leer el cliente enviado:
        String idCliente="";
        try {
            idCliente = is.readUTF();
        } catch (IOException ex) {
            ex.printStackTrace();
            return;
        }
        //Verificar que el cliente ya este:
        ClienteInfo ci=null;
        for (int i = 0; i < listaUsuariosCercanos.size(); i++)
        {
            ci=(ClienteInfo) listaUsuariosCercanos.elementAt(i);
            if (ci.getId().equals(idCliente))
            {
                listaUsuariosCercanos.removeElement(ci);
                clienteListener.recibirClientesCercanos();
                return;
            }
        }
    }
}
